package cn.mulanbay.admin.api.web.aop;

import cn.mulanbay.admin.api.handler.SystemConfigHandler;
import cn.mulanbay.admin.api.persistent.service.RoleService;
import cn.mulanbay.business.handler.CacheHandler;
import cn.mulanbay.business.handler.FeignCheckHandler;
import cn.mulanbay.common.aop.BindUser;
import cn.mulanbay.common.aop.FullEndDateTime;
import cn.mulanbay.common.bean.PageSearch;
import cn.mulanbay.common.config.CacheKey;
import cn.mulanbay.common.exception.ApplicationException;
import cn.mulanbay.common.exception.ErrorCode;
import cn.mulanbay.common.util.DateUtil;
import cn.mulanbay.common.util.StringUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * 全局Aop
 * 登录、权限验证及用户信息的自动注入
 *
 * @author fenghong
 * @create 2022-01-16 10:00
 */
@Component
@Aspect
public class ControllerHandler {

    private static final Logger logger = LoggerFactory.getLogger(ControllerHandler.class);

    @Value("${system.pageSearch.maxPageSize}")
    int maxPageSize;

    @Autowired
    FeignCheckHandler feignCheckHandler;

    @Autowired
    CacheHandler cacheHandler;

    @Autowired
    RoleService roleService;

    @Autowired
    SystemConfigHandler systemConfigHandler;

    private HttpServletRequest getRequest() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes()).getRequest();
        return request;
    }

    /**
     * controller包的子包里面任何方法
     */
    @Pointcut("execution(public * cn.mulanbay.admin.api.web.controller.*.*(..))")
    public void setUserInfo() {
    }

    @Before("setUserInfo()")
    public void beforeBuss(JoinPoint joinPoint) {
        try {
            //检查功能点是否启用
            HttpServletRequest request = this.getRequest();
            String url = request.getServletPath();
            logger.debug("aop拦截："+url);
            String method = request.getMethod();
            //userId由网关设置
            String us = request.getHeader(CacheKey.DETAILS_USER_ID);
            Long userId = null ;
            if(StringUtil.isNotEmpty(us)){
                userId = Long.valueOf(us);
            }
            //roleId由网关设置
            String rs = request.getHeader(CacheKey.DETAILS_ROLE_ID);
            if(StringUtil.isEmpty(rs)){
                //feign内部调用
                int code = feignCheckHandler.checkFeignAuth(request);
                if(code==ErrorCode.SUCCESS){
                    //设置用户等信息
                    handleRequestInfoSet(joinPoint, userId);
                    return;
                }else{
                    throw new ApplicationException(code);
                }
            }
            Long roleId = Long.valueOf(rs);
            int resCode = systemConfigHandler.isRoleAuth(roleId,url,method);
            if(resCode!=ErrorCode.SUCCESS){
                throw new ApplicationException(resCode);
            }
            //设置用户等信息
            handleRequestInfoSet(joinPoint, userId);
        } catch (ApplicationException e) {
            throw e;
        } catch (Exception e) {
            logger.error("do beforeBuss error", e);
            throw new ApplicationException(ErrorCode.SYSTEM_ERROR,e.getMessage());
        }
    }

    /**
     * 获取注解中对方法的描述信息 用于Controller层注解
     *
     * @param joinPoint 切点
     * @return 方法描述
     * @throws Exception
     */
    public void handleRequestInfoSet(JoinPoint joinPoint, Long userId) {
        Object[] arguments = joinPoint.getArgs();
        for (Object arg : arguments) {
            if (arg != null) {
                if (userId != null) {
                    // 个人模式下，直接设置为当前用户
                    if (arg instanceof BindUser) {
                        BindUser bu = (BindUser) arg;
                        bu.setUserId(userId);
                    }
                }
                // 判断分页数据中的最大数
                if (arg instanceof PageSearch) {
                    PageSearch bu = (PageSearch) arg;
                    if (bu.getPageSize() > maxPageSize) {
                        throw new ApplicationException(ErrorCode.PAGE_SIZE_OVER_MAX);
                    }
                }
                //时间查询类添加23:59:59
                if (arg instanceof FullEndDateTime) {
                    FullEndDateTime qwu = (FullEndDateTime) arg;
                    Date endDate = qwu.getEndDate();
                    if (endDate != null) {
                        qwu.setEndDate(DateUtil.getTodayTillMiddleNightDate(endDate));
                    }
                }
            }

        }
    }
}
